package com.laworks.urlutils;


import java.io.BufferedOutputStream;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;




interface DownloaderCallBack
{
    void execute();
}


class TestClass implements DownloaderCallBack
{
    private int testInt = 0;
    private String testString = "Download finished";
    
    
    private void testFunction()
    {
        System.out.println("after down");
    }
    
    @Override
    public void execute()
    {
        // TODO Auto-generated method stub
        System.out.println(testInt + testString);
        testFunction();
    }
}


class SingleImageDownloader implements Callable<String>
{
    private String url;
    private String dirPath = "/sdcard/DownFile/photo/";
    private String fileExtension = "jpg";
    private DownloaderCallBack callback;

    
    public SingleImageDownloader(String url, String dirPath, DownloaderCallBack callback)
    {
        this.url = url;
        this.dirPath = dirPath;
        if(!this.dirPath.endsWith("/"))
        {
            this.dirPath += "/";
        }
        this.callback = callback;
    }

    @Override
    public String call() throws Exception
    {
        System.out.println(Thread.currentThread().getName());
        String fileName = null;
        
        DefaultHttpClient client = new DefaultHttpClient();
        HttpResponse response;
        
        HttpGet request = new HttpGet(url);
        try
        {
            response = client.execute(request);
            StatusLine statusLine = response.getStatusLine();
            int reqCode = statusLine.getStatusCode();
            if (reqCode != HttpStatus.SC_OK)
            {
                throw new Exception("Error in response, response code is: " + reqCode);
            }

            this.getImageType(response);

            HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent();
            
            Random random = new Random(System.currentTimeMillis());
            int fileNo = random.nextInt();
            fileName = this.dirPath + Thread.currentThread().getName() + fileNo + fileExtension;
            File outputFile = new File(fileName);
            FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                    fileOutputStream);

            byte[] byteArray = new byte[4096];
            int len = inputStream.read(byteArray);
            while (len != -1)
            {
                bufferedOutputStream.write(byteArray, 0, len);
                len = inputStream.read(byteArray);
            }
            bufferedOutputStream.flush();
            bufferedOutputStream.close();
        } catch (Exception e)
        {
            throw e;
        }
        
        this.callback.execute();
        
        return fileName;
    }

    private void getImageType(HttpResponse response) throws Exception
    {
        Header[] headers = response.getHeaders("Content-Type");
        String contentType = null;
        if (headers.length > 1)
        {
            throw new Exception();
        }
        contentType = headers[0].toString();

        String patternString = "image.(png|jpeg|jpg)";

        Pattern imageFilePatthen = Pattern.compile(patternString,
                Pattern.CASE_INSENSITIVE);

        Matcher matcher = imageFilePatthen.matcher(contentType);
        if (matcher.find())
        {
            String typeString = matcher.group(1);
            if (typeString.equalsIgnoreCase("jpg")
                    || typeString.equalsIgnoreCase("jpeg"))
            {
                this.fileExtension = ".jpg";
            } else if (typeString.equalsIgnoreCase("png"))
            {
                this.fileExtension = ".png";
            } else if (typeString.equalsIgnoreCase("gif"))
            {
                this.fileExtension = ".gif";
            } else if (typeString.equalsIgnoreCase("bmp"))
            {
                this.fileExtension = ".bmp";
            } else
            {
                throw new Exception();
            }
        }
        else
        {
            throw new Exception();
        }
        return;
    }
}

class MassImageDownloader
{
    public MassImageDownloader(List<String> imageUrlList, DownloaderCallBack callback)
    {
        init(imageUrlList, callback);
        this.threadPool = Executors.newFixedThreadPool(threadPoolSize);
    }
    
    public MassImageDownloader(List<String> imageUrlList, String dirPath, DownloaderCallBack callback)
    {
        init(imageUrlList, callback);
        this.dirPath = dirPath;
        this.threadPool = Executors.newFixedThreadPool(threadPoolSize);
    }
    
    public MassImageDownloader(List<String> imageUrlList, String dirPath, DownloaderCallBack callback, int threadPoolSize)
    {
        init(imageUrlList, callback);
        this.dirPath = dirPath;
        this.threadPoolSize = threadPoolSize;
        this.threadPool = Executors.newFixedThreadPool(threadPoolSize);
    }
    
    private void init(List<String> imageUrlList, DownloaderCallBack callback)
    {
        this.imageUrlList = imageUrlList;
        this.callback = callback;
    }
    
    public void downloadImages()
    {
        for(String url : this.imageUrlList)
        {
            SingleImageDownloader du = new SingleImageDownloader(url, dirPath, new TestClass());
 
            try
            {
                FutureTask<String> futureTask = new FutureTask<String>(du);
                this.threadPool.submit(futureTask);
            } catch (Exception e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        this.threadPool.shutdown();
    }
    
    private int threadPoolSize = 5;
    private String dirPath = "/sdcard/DownFile/photo";
    private List<String> imageUrlList;
    private ExecutorService threadPool;
    private DownloaderCallBack callback;
    
}


public class TestDownloadUtil
{
    /**
     * @param args
     * @throws InterruptedException 
     */
    private static final int THREAD_POOL_SIZE = 5;
    public static void main(String[] args) throws InterruptedException
    {
        // TODO Auto-generated method stub
        ArrayList<String> imageList = new ArrayList<String>();
        for (int i = 1; i < 10; i++)
        {
            String url = "http://127.0.0.1/test/0" + i + ".jpg";
            imageList.add(url);
        }
        
        MassImageDownloader mid = new MassImageDownloader(imageList, "/home/leo/temp", new TestClass());
        mid.downloadImages();
    }
}
